package TheDealmap;

import Data.Businesses;
import Data.Deal;
import Data.Deals;
import Data.GeoCoord;
import Data.ProposedDeal;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

public class Service {

    private static final String SEARCH_DEALS = "http://api.thedealmap.com/search/deals/";
    private static final String SEARCH_BUSINESSES = "http://api.thedealmap.com/search/businesses/";
    private static final String ADD_DEALS = "http://api.thedealmap.com/deals/";
    private String apiKey = "";

    public Service(String apikey) {
        this.apiKey = apikey;
    }

    public Deals SearchDeals(
            int activity,
            int capability,
            Date expirationDate,
            double latitude,
            double longitude,
            String query,
            Double distance,
            Integer startIndex,
            Integer pageSize) throws UnsupportedEncodingException, MalformedURLException, IOException, Exception {

        return SearchDeals(
                this.apiKey,
                activity,
                capability,
                expirationDate,
                latitude,
                longitude,
                query,
                distance,
                startIndex,
                pageSize);
    }

    public static Deals SearchDeals(
            String apiKey,
            int activity,
            int capability,
            Date expirationDate,
            double latitude,
            double longitude,
            String query,
            Double distance,
            Integer startIndex,
            Integer pageSize) throws UnsupportedEncodingException, MalformedURLException, IOException, Exception {

        GeoCoord latLong = new GeoCoord(latitude, longitude);
        String url = BuildGetUrl(
                SEARCH_DEALS,
                apiKey,
                activity,
                capability,
                expirationDate,
                latLong.toString(),
                query,
                distance,
                startIndex,
                pageSize);

        System.out.println(url);

        String results = GetHttpResponse(url);

        Serializer serializer = new Persister();
        ByteArrayInputStream bs = new ByteArrayInputStream(results.getBytes());

        Deals deals = serializer.read(Deals.class, bs);
        return deals;
    }

    public Businesses SearchBusinessListings(
            int activity,
            double latitude,
            double longitude,
            String query,
            Double distance,
            Integer startIndex,
            Integer pageSize) throws Exception {
        return SearchBusinessListings(
                this.apiKey,
                activity,
                latitude,
                longitude,
                query,
                distance,
                startIndex,
                pageSize);
    }

    public static Businesses SearchBusinessListings(
            String apiKey,
            int activity,
            double latitude,
            double longitude,
            String query,
            Double distance,
            Integer startIndex,
            Integer pageSize) throws Exception {
        
        GeoCoord latLong = new GeoCoord(latitude, longitude);
        String url = BuildGetUrl(
                SEARCH_BUSINESSES,
                apiKey,
                activity,
                null,
                null,
                latLong.toString(),
                query,
                distance,
                startIndex,
                pageSize);

        System.out.println(url);

        String results = GetHttpResponse(url);

        Serializer serializer = new Persister();
        ByteArrayInputStream bs = new ByteArrayInputStream(results.getBytes());

        Businesses businesses = serializer.read(Businesses.class, bs);
        return businesses;
    }

    public Deal GetDealDetails(String dealId) {
        return GetDealDetails(this.apiKey, dealId);
    }

    public static Deal GetDealDetails(String apiKey, String dealId) {
        return new Deal();
    }

    public String SubmitDeal(ProposedDeal newDeal) throws Exception {
        return SubmitDeal(this.apiKey, newDeal);
    }

    public static String SubmitDeal(String apiKey, ProposedDeal newDeal) throws Exception {
        Serializer serializer = new Persister();
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        serializer.write(newDeal, outStream);
        System.out.println(outStream.toString());
        return PostHttpRequest(ADD_DEALS, outStream.toString());
    }

    private static String BuildGetUrl(
            String url,
            String apikey,
            Integer activity,
            Integer capability,
            Date expirationDate,
            String location,
            String query,
            Double distance,
            Integer startIndex,
            Integer pageSize) throws UnsupportedEncodingException {
        Map<String, String> params = new HashMap<String, String>();
        if (location != null) {
            params.put("l", location);
        }
        if (query != null) {
            params.put("q", query);
        }
        if (distance != null) {
            params.put("d", distance.toString());
        }
        if (startIndex != null) {
            params.put("si", startIndex.toString());
        }
        if (pageSize != null) {
            params.put("ps", pageSize.toString());
        }
        if (activity != null) {
            params.put("a", activity.toString());
        }
        if (capability != null) {
            params.put("c", capability.toString());
        }
        if (expirationDate != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            params.put("ed", sdf.format(expirationDate));
        }
        if (apikey != null) {
            params.put("key", apikey);
        }


        StringBuilder paramString = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            paramString.append(entry.getKey());
            paramString.append('=');
            paramString.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            paramString.append("&");
        }
        // Remove the tailing &
        paramString.delete(paramString.length() - 1, paramString.length());

        return url + '?' + paramString.toString();
    }

    private static String PostHttpRequest(String urlLocation, String postData)
            throws MalformedURLException, IOException {
        StringBuilder sb = new StringBuilder();
        Map<String, String> params = new HashMap<String, String>();

        // Construct data
        // String data = encodePostParams(postData);
        // Send data
        URL url = new URL(urlLocation);
        
        URLConnection conn = url.openConnection();
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setRequestProperty("Content-Type", "application/xml; charset=utf-8");
        Integer length = postData.getBytes("UTF-8").length;
        String le = length.toString();
        conn.setRequestProperty("Content-Length", le);

        OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
        wr.write(postData);
        wr.flush();

        // Get the response
        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line;
        
        while ((line = rd.readLine()) != null) {
            sb.append(line);
        }
        wr.close();
        rd.close();


        return sb.toString();
    }

    private static String GetHttpResponse(String urlLocation) throws MalformedURLException, IOException {
        StringBuilder sb = new StringBuilder();
        URL url = new URL(urlLocation);
        URLConnection conn = url.openConnection();
        conn.setDoOutput(true);

        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line;
        while ((line = rd.readLine()) != null) {
            sb.append(line);
        }
        //wr.close();
        rd.close();
        System.out.println(sb.toString());

        return sb.toString();
    }

    private class SearchBuilder {
    }
}


